package com.bstek.uflo.designer.deserializer.impl;

import java.util.List;

import org.dom4j.Element;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.bstek.uflo.designer.model.AssignmentType;
import com.bstek.uflo.designer.model.CalendarInfo;
import com.bstek.uflo.designer.model.Shape;
import com.bstek.uflo.designer.model.TaskAssignee;
import com.bstek.uflo.designer.model.UserData;
import com.bstek.uflo.designer.model.node.Task;

/**
 * @author matt.yao@bstek.com
 * @since 1.0
 */
@Service
public class TaskDeserializer extends NodeDeserializer {

	public Shape execute(Element currentElement) throws Exception {
		Task task = new Task();
		super.deserializeCommonAttribute(task, currentElement);
		String taskName = currentElement.attributeValue("task-name");
		String url = currentElement.attributeValue("url");
		String taskType = currentElement.attributeValue("task-type");

		task.setTaskName(taskName);
		task.setUrl(url);
		task.setTaskType(taskType);

		String countersignMultiplicity = currentElement.attributeValue("countersign-multiplicity");
		String countersignPercentMultiplicity = currentElement.attributeValue("countersign-percent-multiplicity");
		String countersignExpression = currentElement.attributeValue("countersign-expression");
		String countersignHandler = currentElement.attributeValue("countersign-handler");

		if (StringUtils.hasText(countersignMultiplicity)) {
			task.setCounterSignType("countersignMultiplicity");
			task.setCountersignMultiplicity(Integer.parseInt(countersignMultiplicity));
		} else if (StringUtils.hasText(countersignPercentMultiplicity)) {
			task.setCounterSignType("countersignPercentMultiplicity");
			task.setCountersignPercentMultiplicity(Integer.parseInt(countersignPercentMultiplicity));
		} else if (StringUtils.hasText(countersignExpression)) {
			task.setCounterSignType("countersignExpression");
			task.setCountersignExpression(countersignExpression);
		} else if (StringUtils.hasText(countersignHandler)) {
			task.setCounterSignType("countersignHandler");
			task.setCountersignHandler(countersignHandler);
		} else {
			task.setCounterSignType("countersignNone");
		}

		String allowSpecifyAssignee = currentElement.attributeValue("allow-specify-assignee");
		if (StringUtils.hasText(allowSpecifyAssignee)) {
			task.setAllowSpecifyAssignee(Boolean.valueOf(allowSpecifyAssignee));
		}
		String assignmentType = currentElement.attributeValue("assignment-type");
		task.setAssignmentType(assignmentType);
		task.setSwimlane(currentElement.attributeValue("swimlane"));
		task.setExpression(currentElement.attributeValue("expression"));
		task.setAssignmentHandlerBean(currentElement.attributeValue("assignment-handler-bean"));
		if (assignmentType.equals(AssignmentType.Assignee.name())) {
			List<?> taskAssigneeElements = currentElement.elements("assignee");
			for (Object taskAssigneeObj : taskAssigneeElements) {
				Element taskAssigneeElement = (Element) taskAssigneeObj;
				TaskAssignee taskAssignee = new TaskAssignee();
				taskAssignee.setId(taskAssigneeElement.attributeValue("id"));
				taskAssignee.setName(taskAssigneeElement.attributeValue("name"));
				taskAssignee.setProviderId(taskAssigneeElement.attributeValue("provider-id"));
				task.getTaskAssignees().add(taskAssignee);
			}
		}
		this.deserializeTaskDueAttribute(task, currentElement);
		this.deserializeUserDataAttribute(task, currentElement);
		return task;
	}

	private void deserializeTaskDueAttribute(Task task, Element taskElement) {
		Element dueElement = taskElement.element("due");
		if (dueElement != null) {
			task.setUseDue(true);
			String dueDay = dueElement.attributeValue("day");
			String dueDour = dueElement.attributeValue("hour");
			String dueMinute = dueElement.attributeValue("minute");
			if (StringUtils.hasText(dueDay)) {
				task.setDueDay(Integer.parseInt(dueDay));
			}
			if (StringUtils.hasText(dueDour)) {
				task.setDueDour(Integer.parseInt(dueDour));
			}
			if (StringUtils.hasText(dueMinute)) {
				task.setDueMinute(Integer.parseInt(dueMinute));
			}
			List<?> calendarInfoElements = dueElement.elements("calendar-provider");
			for (Object calendarInfoObj : calendarInfoElements) {
				Element calendarInfoElement = (Element) calendarInfoObj;
				CalendarInfo calendarInfo = new CalendarInfo();
				calendarInfo.setId(calendarInfoElement.attributeValue("id"));
				calendarInfo.setName(calendarInfoElement.attributeValue("name"));
				task.getDueCalendarInfos().add(calendarInfo);
			}
			this.deserializeTaskReminderAttribute(task, dueElement);
		}
	}

	private void deserializeTaskReminderAttribute(Task task, Element dueElement) {
		Element onceReminderElement = dueElement.element("once-reminder");
		Element periodReminderElement = dueElement.element("period-reminder");
		if (onceReminderElement != null) {
			task.setReminderType("once");
			task.setReminderHandlerBean(onceReminderElement.attributeValue("handler-bean"));
		} else if (periodReminderElement != null) {
			task.setReminderType("period");
			task.setReminderHandlerBean(periodReminderElement.attributeValue("handler-bean"));
			String repeat = periodReminderElement.attributeValue("repeat");
			if (StringUtils.hasText(repeat)) {
				task.setReminderRepeat(Integer.parseInt(repeat));
			}
			task.setReminderDateUnit(periodReminderElement.attributeValue("unit"));
			List<?> periodReminderElements = periodReminderElement.elements("calendar-provider");
			for (Object calendarInfoObj : periodReminderElements) {
				Element calendarInfoElement = (Element) calendarInfoObj;
				CalendarInfo calendarInfo = new CalendarInfo();
				calendarInfo.setId(calendarInfoElement.attributeValue("id"));
				calendarInfo.setName(calendarInfoElement.attributeValue("name"));
				task.getReminderCalendarInfos().add(calendarInfo);
			}
		}
	}

	private void deserializeUserDataAttribute(Task task, Element taskElement) {
		List<?> userDataElements = taskElement.elements("user-data");
		for (Object userDataElementObj : userDataElements) {
			Element userDataElement = (Element) userDataElementObj;
			UserData userData = new UserData();
			userData.setValue(userDataElement.attributeValue("value"));
			userData.setKey(userDataElement.attributeValue("key"));
			task.getUserData().add(userData);
		}
	}

	public boolean support(String name) {
		return name.equals("task") ? true : false;
	}

}
